home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 7 / Gekikoh Dennoh Club Vol. 7 (Japan).7z / Gekikoh Dennoh Club Vol. 7 (Japan) (Track 01).bin / games / otoko / source.lzh / enemy.c < prev    next >
C/C++ Source or Header  |  1999-06-14  |  9KB  |  380 lines

  1. #include "otoko.h"
  2. #include "player.h"
  3. #include "shot.h"
  4. #include "enemy.h"
  5. #include "psearch.h"
  6. #include "damage.h"
  7.  
  8. #ifndef NULL
  9. #define NULL ((void *) 0)
  10. #endif
  11.  
  12.  
  13. #define ENEMY_MAX    32    /* 敵最大数 */
  14.  
  15. static ENEMY enemy[ENEMY_MAX];    /* ワーク */
  16. static ENEMY *enemy_top,    /* 使用中のワークのリスト */
  17.  *enemy_null_top,        /* 空のワークのリスト */
  18.  *enemy_end;            /* 使用中ワークのリストの末尾 */
  19.  
  20.  
  21. /* ショットが敵キャラに与えるダメージ(添え時は出現してからのフレーム数) */
  22. static short shot_damage[]=
  23. {
  24.     4, 4, 4, 4, 3, 3, 3, 3, 3, 3,
  25.     2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  26.     2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  27.     2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  28.     2, 2, 2, 2, 2, 2, 2, 2, 2, 2
  29. };
  30.  
  31. /* ショットが敵キャラに与えるダメージ(添え時は出現してからのフレーム数) */
  32. /* コアに当てた時 */
  33. static short shot_damage_core[]=
  34. {
  35.     6, 6, 6, 6, 5, 5, 5, 5, 4, 4,
  36.     4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
  37.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  38.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  39.     3, 3, 3, 3, 3, 3, 3, 3, 3, 3
  40. };
  41. /* ちなみにショットは 7dot/frame だ */
  42.  
  43. #define BLASER_HITX    16
  44.  
  45.  
  46. #define wabs(x) ((x) >= 0 ? (short) (x) : (short) -(x))
  47. #define abs(x)  ((x) >= 0 ? (int) (x) : (int) -(x))
  48.  
  49.  
  50. typedef void (*func_init) (struct _enemy *);
  51. func_init FuncEnemyInit[]=
  52. {
  53.     EnemyInitBoss02,
  54.     EnemyInitBoss03,
  55.     EnemyInitCoverF,
  56.     EnemyInitCoverN,
  57.     EnemyInitCoverN2,
  58.     EnemyInitLBoss01,
  59.     EnemyInitLBoss01C,
  60.     EnemyInitLBoss02,
  61.     EnemyInitLBoss02E,
  62.     EnemyInitLBoss02H,
  63.     EnemyInitLBoss02W,
  64.     EnemyInitLBoss03,
  65.     EnemyInitLBoss03G,
  66.     EnemyInitLBoss03P,
  67.     EnemyInitLBoss03U,
  68.     EnemyInitLBoss03Z,
  69.     EnemyInitLBoss04,
  70.     EnemyInitLBoss04C,
  71.     EnemyInitLBoss04E,
  72.     EnemyInitLBoss04S,
  73.     EnemyInitLBoss04V,
  74.     EnemyInitLBoss04W,
  75.     EnemyInitMvLaser,
  76.     EnemyInitMvLaserH,
  77.     EnemyInitOpLaser,
  78.     EnemyInitOpLinear,
  79.     EnemyInitRound4,
  80.     EnemyInitSearchZ,
  81.     EnemyInitSword,
  82.     EnemyInitSword2,
  83.     EnemyInitZako02,
  84.     EnemyInitZako031,
  85.     EnemyInitZako032,
  86.     EnemyInitZako033,
  87.     EnemyInitZako04,
  88.     EnemyInitZako041,
  89. };
  90.  
  91.  
  92.  
  93. /* 起動時に1度だけ呼ばれる */
  94. void EnemyInit0 (void)
  95. {
  96.     int i;
  97.  
  98.     /* リストをつなげる */
  99.     enemy_top = NULL;
  100.     enemy_end = NULL;
  101.     enemy_null_top = enemy;
  102.     for (i = 0; i < ENEMY_MAX; i++)
  103.         enemy[i].next = &enemy[i + 1];
  104.  
  105.     enemy[ENEMY_MAX - 1].next = NULL;
  106. }
  107.  
  108.  
  109.  
  110. /* ゲーム開始時に1度だけ呼ばれる */
  111. /* 「初めの8機ぶんだけ得点を表示」に使用する static 変数を初期化する */
  112. void EnemyInitStatic (void)
  113. {
  114.     EnemyInitStaticLBoss03G ();
  115.     EnemyInitStaticSearchZ ();
  116.     EnemyInitStaticZako02 ();
  117.     EnemyInitStaticZako031 ();
  118.     EnemyInitStaticZako032 ();
  119.     EnemyInitStaticZako033 ();
  120.     EnemyInitStaticZako04 ();
  121.     EnemyInitStaticZako041 ();
  122. }
  123.  
  124.  
  125.  
  126. /* 敵出現時に呼ばれる */
  127. ENEMY *EnemyInit (short type, signed short x, signed short y,
  128.           short arg, struct _enemy *parent)
  129. {
  130.     ENEMY *p;
  131.  
  132.     if (enemy_null_top == NULL)
  133.         return (NULL);    /* 空きのワークがない(キャラクターオーバー) */
  134.  
  135.     /* リストの末尾に新しいノードを追加(他とは違うので注意) */
  136.     p = enemy_null_top;
  137.     enemy_null_top = p->next;
  138.     if (enemy_top == NULL)
  139.         enemy_top = p;
  140.     else
  141.         enemy_end->next = p;
  142.     p->next = NULL;
  143.     enemy_end = p;
  144.  
  145.     p->type = type;
  146.     p->arg = arg;
  147.     p->lx = x << 16;
  148.     p->ly = y << 16;
  149.     p->parent = parent;
  150.     p->child_kill = p->child_death = 0;
  151.     FuncEnemyInit[type] (p);/* 初期化ルーチンへ飛ぶ(関数へのポインタってヤツ) */
  152.  
  153.     return (p);        /* 作成したワークへのポインタを返す */
  154. }
  155.  
  156.  
  157.  
  158. /* 垂直同期ごとに呼ばれる */
  159. void EnemyMove (void)
  160. {
  161.     ENEMY *p, *q;
  162.     signed short pl_x = player->x, pl_y = player->y;
  163.  
  164. #ifdef DEBUG
  165.     enemy_sum = 0;
  166. #endif
  167.  
  168.     p = enemy_top;        /* 現在注目しているワーク */
  169.     q = NULL;        /* 1つ前のワーク(ワーク削除時に必要) */
  170.     while (p != NULL) {
  171. #ifdef DEBUG
  172.         enemy_sum++;
  173. #endif
  174.         /* 移動関数を呼ぶ(関数へのポインタってヤツ) */
  175.         if ((p->func_enemy_move) (p)) {    /* 返り値が非0なら消去 */
  176.             (p->func_enemy_tini) (p);    /* 消去関数を呼ぶ */
  177.             if (q == NULL) {    /* リストの一番最初を削除 */
  178.                 enemy_top = p->next;
  179.                 p->next = enemy_null_top;
  180.                 enemy_null_top = p;
  181.                 q = NULL;
  182.                 p = enemy_top;
  183.             } else {
  184.                 if (p == enemy_end) {    /* リストの一番最後を削除 */
  185.                     q->next = NULL;
  186.                     enemy_end = q;
  187.                     p->next = enemy_null_top;
  188.                     enemy_null_top = p;
  189.                     p = q->next;
  190.                 } else {
  191.                     q->next = p->next;
  192.                     p->next = enemy_null_top;
  193.                     enemy_null_top = p;
  194.                     p = q->next;
  195.                 }
  196.             }
  197.         } else {
  198.             SHOT *p2 = shot_top;    /* 現在注目しているショットのワーク */
  199.             signed short t;
  200.             /* プレイヤーとの当たり判定 */
  201.             if (((t = p->x + p->hit_px) > pl_x)
  202.                 && ((t -= (short) (p->hit_px << 1)) < pl_x)
  203.                 && ((t = p->y + p->hit_py) > pl_y)
  204.                 && ((t -= (short) (p->hit_py << 1)) < pl_y)) {
  205.                 if (player->seq == PLAYER_SEQ_ALIVE) {
  206.                     player->seq = PLAYER_SEQ_DEAD;
  207.                 } else {
  208.                     short hit_w;
  209.                     /* 無敵状態で当たった */
  210.                     if (((t = p->x + (hit_w = p->hit_cx)) >= pl_x)
  211.                         && ((t -= (short) (hit_w << 1)) <= pl_x)) {
  212.                         /* コアに当たった */
  213.                         p->damage += PLAYER_DAMAGE_CORE;
  214.                         p->damage_core = !0;
  215.                     } else {
  216.                         /* それ以外の部分に当たった */
  217.                         p->damage += PLAYER_DAMAGE;
  218.                     }
  219.                 }
  220.             }
  221.             /* ショットとの当たり判定 */
  222.             while (p2 != NULL) {
  223.                 signed short p2_w;
  224.                 short hit_w;
  225.                 if (((t = p->x + (hit_w = p->hit_sx)) >= (p2_w = *((short *) (&p2->lx))))
  226.                     && ((t -= (short) (hit_w << 1)) <= p2_w)
  227.                     && ((t = p->y + (hit_w = p->hit_sy)) >= (p2_w = *((short *) (&p2->ly))))
  228.                     && ((t -= (short) (hit_w << 1)) <= p2_w)
  229.                     && (p2->damage == 0)) {
  230.                     p2->damage = !0;
  231.                     if (((t = p->x + (hit_w = p->hit_cx)) >= (p2_w = *((short *) (&p2->lx))))
  232.                         && ((t -= (short) (hit_w << 1)) <= p2_w)) {
  233.                         /* コアに当たった */
  234.                         p->damage += shot_damage_core[p2->frame];
  235.                         p->damage_core = !0;
  236.                     } else {
  237.                         /* それ以外の部分に当たった */
  238.                         p->damage += shot_damage[p2->frame];
  239.                     }
  240.                 }
  241.                 p2 = p2->next;
  242.             }
  243.             /* ボンバーとの当たり判定 */
  244.             if (p->hit_sx != 0) {
  245.                 switch (player->bomb_hitcheck) {
  246.                 case BOMB_NON:
  247.                     break;
  248.                 case BOMB_A:
  249.                     p->damage += BOMBER_DAMAGE;
  250.                     break;
  251.                 case BOMB_B:
  252.                     if (p->y > pl_y)
  253.                         p->damage += BACK_B_DAMAGE;
  254.                     break;
  255.                 case BOMB_C:
  256.                     {
  257.                         short hit_w;
  258.                         if (((t = p->x + (hit_w = p->hit_sx)) >= pl_x)
  259.                             && ((t -= (short) (hit_w << 1)) <= pl_x)
  260.                             && (p->y <= pl_y)) {
  261.                             if (((t = p->x + (hit_w = p->hit_cx)) >= pl_x)
  262.                                 && ((t -= (short) (hit_w << 1)) <= pl_x)) {
  263.                                 /* コアに当たった */
  264.                                 p->damage += BLASER_DAMAGE_CORE;
  265.                                 p->damage_core = !0;
  266.                             } else {
  267.                                 /* それ以外の部分に当たった */
  268.                                 p->damage += BLASER_DAMAGE;
  269.                             }
  270.                         }
  271.                     } break;
  272.                 }
  273.             }
  274.             q = p;
  275.             p = p->next;
  276.         }
  277.     }
  278. }
  279.  
  280.  
  281.  
  282. /* 敵消去時に呼ばれる(ゲームオーバー時) */
  283. void EnemyTini (void)
  284. {
  285.     int i;
  286.  
  287.     /* リストをつなげる */
  288.     enemy_top = NULL;
  289.     enemy_null_top = enemy;
  290.     for (i = 0; i < ENEMY_MAX; i++)
  291.         enemy[i].next = &enemy[i + 1];
  292.  
  293.     enemy[ENEMY_MAX - 1].next = NULL;
  294. }
  295.  
  296.  
  297.  
  298. /* サービスルーチン */
  299.  
  300. enum {
  301.     MOVESEQ_ADD, MOVESEQ_FIX, MOVESEQ_SUB, MOVESEQ_END
  302. };
  303.  
  304. /* 絶対座標 dx,dy に向かって移動する(初期化) */
  305. void SubEnemyMoveToInit (ENEMY * p, signed short dest_x, signed short dest_y,
  306.              unsigned char speed, signed short count)
  307. {
  308.     unsigned char angle;
  309.     signed short sx, sy;
  310.  
  311.     sx = wabs (dest_x - p->x);
  312.     sy = wabs (dest_y - p->y);
  313.     angle = msearch (p->x, p->y, dest_x, dest_y);    /* 移動方向 */
  314.     p->move_ax = vxtable[speed][angle] / 32;
  315.     p->move_ay = vytable[speed][angle] / 32;
  316.  
  317.     p->move_counter = p->move_count = count;    /* 何回加速/減速するか */
  318.  
  319.     /* 誤差を少なくするために大きい方で計算 */
  320.     /* 除数が絶対に 0 にならないようにするため +1 しています(小細工) */
  321.     if (sx > sy)
  322.         p->move_count2 = sx * 65536 / (abs (p->move_ax * count) + 1) - count;
  323.     else
  324.         p->move_count2 = sy * 65536 / (abs (p->move_ay * count) + 1) - count;
  325.  
  326.     p->move_count3 = 0;    /* 実際に加速/減速した回数 */
  327.     p->move_seq = MOVESEQ_ADD;
  328. }
  329.  
  330.  
  331.  
  332. /* 座標 dx,dy に向かって移動する */
  333. short SubEnemyMoveTo (ENEMY * p)
  334. {
  335.     switch (p->move_seq) {
  336.         case MOVESEQ_ADD:    /* 加速中 */
  337.         p->vx += p->move_ax;
  338.         p->vy += p->move_ay;
  339.         p->move_count3++;
  340.         if (p->move_counter-- <= 0) {
  341.             p->move_seq++;    /* 加速したら次へ */
  342.             p->move_counter = p->move_count2;
  343.         }
  344.         break;
  345.     case MOVESEQ_FIX:    /* 等速度運動中 */
  346.         if (p->move_counter-- <= 0) {
  347.             p->move_seq++;    /* 加速したら次へ */
  348.             p->move_counter = p->move_count;
  349.         }
  350.         break;
  351.     case MOVESEQ_SUB:    /* 減速中 */
  352.         p->vx -= p->move_ax;
  353.         p->vy -= p->move_ay;
  354.         p->move_count3--;
  355.         if (p->move_counter-- <= 0)    /* ある程度減速したら次へ */
  356.             p->move_seq++;
  357.         break;
  358.     case MOVESEQ_END:
  359.         p->vx = p->vy = p->move_ax = p->move_ay = 0;
  360.         return (-1);
  361.     }
  362.     return (0);
  363. }
  364.  
  365.  
  366.  
  367. /* 移動を中断する */
  368. short SubEnemyMoveToAbort (ENEMY * p)
  369. {
  370.     if (p->move_count3-- <= 0) {
  371.         p->vx = 0;
  372.         p->vy = 0;
  373.         return (-1);
  374.     }
  375.     p->vx -= p->move_ax;
  376.     p->vy -= p->move_ay;
  377.  
  378.     return (0);
  379. }
  380.